package com.hmsm.server.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;

/**
 * 
 *  @描述:反射帮助类
 *  @作者:yaosq
 *  @创建日期:2014-4-1 下午03:42:38  
 *
 */
public class ReflectBeanHelp {

	/**
	 * 
	 *  @描述:根据一个javaBean对象返回这个对象的所有属性名称和属性值
	 *  @方法名称:getJavaBeanFieldAll
	 *  @作者:yaosq
	 *  @创建日期:2014-4-1 下午03:42:50 
	 *  @param object
	 *  @return
	 *
	 */
	public Map<String, Object> getJavaBeanFieldAll(Object object) {
		Map<String, Object> fieldArr = new HashMap<String, Object>();
		// 获取属性名称

		for (PropertyDescriptor dd:PropertyUtils.getPropertyDescriptors(object.getClass())) {
			
			String fieldStr = dd.getName();
			if(!fieldStr.equalsIgnoreCase("class")){
				// 获取属性名称
				Object value = null;
				try {
					value = getPropertyValue(object, fieldStr);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (value != null) {
					fieldArr.put(fieldStr, value);
				}
			}
			
		}
		return fieldArr;
	}

	/**
	 * 循环向上转型,获取对象的DeclaredField.
	 * 
	 * @throws NoSuchFieldException
	 *             如果没有该Field时抛出.
	 */
	public static Field getDeclaredField(Class<?> clazz, String propertyName) throws NoSuchFieldException {
		Field field = null;

		if(clazz==null||clazz==Object.class){
			throw new NoSuchFieldException("没找指定有效的对象类型：("+clazz+")");
		}else if (propertyName == null || propertyName.length() == 0) {
			throw new NoSuchFieldException("没找指定有效的属性名：("+propertyName+")");
		}else{
			for (Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
				try {
					field = superClass.getDeclaredField(propertyName);
					return field;
				} catch (NoSuchFieldException e) {
					// Field不在当前类定义,继续向上转型
				}
			}
			throw new NoSuchFieldException("No such field: " + clazz.getName() + '.' + propertyName);
		}
	}

	/**
	 * 按FiledName获得Field的类型.
	 */
	public static Class<?> getPropertyType(Class<?> clazz, String name) throws NoSuchFieldException {
		return getDeclaredField(clazz, name).getType();
	}
		
	/**
	 * 解析属性值，并分析需要添加的外键关联
	 * @param clazz
	 * @param example
	 * @param propertyName
	 * @param aliasMap
	 * @return
	 * @throws Exception
	 */
	public static <T> Object getPropertyValue(T example, String propertyName) throws Exception{
		Object value = null;
		
		// 相应属性Setter方法应有的参数类型
		Class<?> paraClass = null;
		// 相应属性Getter方法获得的值类型
		Class<?> valueClass = null;
	
		// 检查属性中的外键关联
		String[] names = propertyName.split("\\.");
		if (names.length > 1) {
			// 有外键需要关联
			String associationPath = null;
			String aliasName = null;
			
			valueClass = example.getClass();
			Object entity = example;
	
			// 逐级解析值类型
			for (int i = 0; i < names.length - 1; i++) {
				if (associationPath == null) {
					associationPath = names[i];
				} else {
					associationPath += "." + names[i];
				}
				aliasName = names[i];
	
				if (entity != null) {
					// 迭代为下一级关联对象
					valueClass = getPropertyType(valueClass, names[i]);
					entity = PropertyUtils.getProperty(entity, names[i]);
					
					if (valueClass.isAssignableFrom(Collection.class) && entity != null&&((Collection<?>) entity).size()==1) {
						// 如果是一个非空集合类型，才需要关联，并且只取一个条目
						for (Object item : (Collection<?>) entity) {
							entity = item;
							valueClass = entity.getClass(); 
							break;
						}
					}
				}
			}
	
			if (entity != null) {
				try {
					value = PropertyUtils.getProperty(entity, names[names.length - 1]);
				} catch (Exception e) {
					value = null;
				}
			}
		} else {
			// 不需要关联外键，直接获取类型及值
			try {
				value = PropertyUtils.getProperty(example, propertyName);
			} catch (Exception e) {
				value = null;
			}
		}
		
		return value;
	}

	/**
	 * 
	 *  @描述:获取对象的名称
	 *  @方法名称:getObjectName
	 *  @作者:yaosq
	 *  @创建日期:2014-4-1 下午03:46:06 
	 *  @param obj
	 *  @return
	 *
	 */
	public String getObjectName(Object obj) {
		return obj.getClass().getSimpleName();
	}

	/**
	 * 
	 *  @描述:获取对象的首字母小写名称
	 *  @方法名称:getObjectNameByLowerCase
	 *  @作者:yaosq
	 *  @创建日期:2014-4-1 下午03:46:17 
	 *  @param obj
	 *  @return
	 *
	 */
	public String getObjectNameByLowerCase(Object obj) {
		String name = this.getObjectName(obj);
		if (name.length() > 1) {
			char fristName = name.charAt(0);
			// 将大写转换小写
			if ((int) fristName < 97) {
				fristName = (char) (fristName + 32);
			}
			String endName = name.substring(1, name.length());
			name = fristName + endName;
		}
		return name;
	}

	public static void main(String[] args) {
		ReflectBeanHelp help = new ReflectBeanHelp();
		System.out.println(help.getObjectNameByLowerCase(help));
	}
}
